package com.jingdianjichi.wx.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis的config处理,都是固定的写法
 */
@Configuration
public class RedisConfig {
    /**
     * 如何我们不去替换的话,我们的RedisTemplate默认使用的是JDK的序列化方式,序列化出来就是乱码,我们去做替换亲
     */

    //重写RedisTemplate的Bean,替换成我们的jackson,如果你的版本比较高的话其实就不会乱码了亲,参数就是链接工工厂来的
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        //自己的RedisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        //声明一些序列化的方式,从而解决乱码,String的序列化方式
        RedisSerializer<String> redisSerializer=new StringRedisSerializer();

        //设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //使用我们自己的序列化方式
        redisTemplate.setKeySerializer(redisSerializer);

        //设置哈希类型的key
        redisTemplate.setHashKeySerializer(redisSerializer);

        //value的值,可以是对象的,所以我们要配个jackson完成亲
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());

        return redisTemplate;
    }


    //jackson的序列化器
    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer(){
        //用自己的
        Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        //帮助我们序列化器设置一些属性
        ObjectMapper objectMapper=new ObjectMapper();
        /*
            PropertyAccessor.ALL 表示对所有类型的访问器（字段、getter、setter等）进行可见性设置。
            JsonAutoDetect.Visibility.ANY 表示所有的属性，即使是私有的也会被序列化和反序列化。
         */

        //这个方法按照那些规则去序列化,下面都是固定的写法
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        //序列化的时候,赵达不到属性的时候,也不会去报错的
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);

        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        //放进去
        jsonRedisSerializer.setObjectMapper(objectMapper);

        return jsonRedisSerializer;
    }
}
